
// === uuMeta ===
// depend: none
/*
window.UUMETA_DEBUG_ALERT = 0;
uuMeta.ie
uuMeta.iemode8
uuMeta.quirks
uuMeta.opera
uuMeta.gecko
uuMeta.gecko191 - Firefox3.5+
uuMeta.firefox
uuMeta.webkit
uuMeta.webkit522 - Safari3+, Chrome1+
uuMeta.webkit530 - Safari4+, Chrome2+
uuMeta.safari
uuMeta.chrome
uuMeta.iphone
uuMeta.uaver
uuMeta.slver
uuMeta.flashver
uuMeta.enginever
uuMeta.canvas
uuMeta.runstyle
uuMeta.debugAlert
uuMeta.hex
uuMeta.mix(base, flavor, aroma = undef, override = true) - return base
uuMeta.toArray(fake) - return array
-- element unique id ---
uuMeta.uid(elm) - return id
--- boot ---
window.boot - user defined boot loader
uuMeta.boot(callback, highPriority = false)
--- event ---
uuMeta.event.bind(elm, eventName, fn, capture)
uuMeta.event.unbind(elm, eventName, fn, capture)
uuMeta.event.stop(evt)
 */
(function() {
var _meta,  // inner namespace
    _uid,   // inner namespace
    _boot,  // inner namespace
    _event, // inner namespace
    _win = window,
    _doc = document,
    _debugAlert = (_win.UUMETA_DEBUG_ALERT || 0),
    _float = parseFloat,
    _nu = navigator.userAgent,
    _ie = !!_doc.uniqueID,
    _opera = !!_win.opera,
    _gecko = _nu.indexOf("Gecko/") > 0,
    _webkit = _nu.indexOf("WebKit") > 0,
    _chrome = _nu.indexOf("Chrome") > 0,
    _uaver = _opera ? _float((opera.version() - 0).toFixed(1)) // Opera10 shock
                    : _float((/(?:IE |fox\/|ome\/|ion\/)(\d+\.\d)/.
                             exec(_nu) || [,0])[1]),
    _slver = (function() {
      try {
        var a = ["1.0", "2.0", "3.0"], i = 3, ok,
            o = _ie ? new ActiveXObject("AgControl.AgControl")
                    : navigator.plugins["Silverlight Plug-In"];
        while (i--) {
          ok = _ie ? o.IsVersionSupported(a[i])
                   : _float(/\d+\.\d+/.exec(o.description)[0]) >= _float(a[i]);
          if (ok) {
            return _float(a[i]);
          }
        }
      } catch(err) {}
      return 0;
    })(),
    _flashver = (function() {
      try {
        var o = _ie ? new ActiveXObject("ShockwaveFlash.ShockwaveFlash")
                    : navigator.plugins["Shockwave Flash"],
            v = _ie ? o.GetVariable("$version").replace(/,/g, ".")
                    : o.description,
            m = /\d+\.\d+/.exec(v);
        return m ? _float(m[0], 10) : 0;
      } catch(err) {}
      return 0;
    })(),
    _egver = _float(((/(?:rv\:|ari\/|sto\/)(\d+\.\d+(\.\d+)?)/.
      exec(_nu) || [,0])[1]).toString().
      replace(/[^\d\.]/g, "").replace(/^(\d+\.\d+)(\.(\d+))?$/, "$1$3")
    ),
    _hex = (function() {
      var r = [], i = 256;
      for(; i < 512; ++i) {
        r.push(i.toString(16).slice(1));
      }
      return r;
    })(),
    _mix = function(base,       // @param Hash: mixin base
                    flavor,     // @param Hash: add flavor
                    aroma,      // @param Hash(= undefined): add aroma
                    override) { // @param Boolean(= true): true is override
                                // @return Hash: base
      var i, ride = (override === void 0) || override;

      for (i in flavor) {
        if (ride || !(i in base)) {
          base[i] = flavor[i];
        }
      }
      return aroma ? _meta.mix(base, aroma, void 0, ride) : base;
    },
    _toArray = function(fake) { // @param NodeList/Array:
                                // @return Array:
      if (!_ie && (_opera && _uaver >= 9.5)) {
        return Array.prototype.slice.call(fake, 0);
      }
      var rv = [], ri = -1, i = 0, iz = fake.length;
      for (; i < iz; ++i) {
        rv[++ri] = fake[i];
      }
      return rv;
    },
    _bootFire = 0, // fired flag
    _bootOrder = [[], []], // [high, low]
    UNIQUEID = "uuqid";

_meta = {
  ie:         _ie,
  iemode8:    _ie && _doc.documentMode >= 8,
  quirks:     (_doc.compatMode || "") !== "CSS1Compat",
  opera:      _opera,
  gecko:      _gecko,
  gecko191:   (_gecko && _egver >= 19.1), // Firefox3.5+
  firefox:    _nu.indexOf("Firefox/") > 0,
  webkit:     _webkit,
  webkit522:  (_webkit && _egver >= 522), // Safari3+, Chrome1+
  webkit530:  (_webkit && _egver >= 530), // Safari4+, Chrome2+
  chrome:     _chrome,
  safari:     !_chrome && _nu.indexOf("Safari") > 0,
  iphone:     _webkit && /iPod|iPhone/.test(_nu),
  uaver:      _uaver,     // User Agent version
  slver:      _slver,     // Silverlight version
  flashver:   _flashver,  // Flash version(ver 7 later)
  enginever:  _egver,     // Render engine version
  canvas:     (_ie && _uaver >= 6) || // <canvas> support
              (_opera  && _uaver >= 9.2) ||
              (_gecko  && _egver >= 18.1) ||
              (_webkit && _egver >= 522),
  runstyle:   _ie ? "currentStyle"
                  : (_win.getComputedStyle ||
                     _doc.defaultView.getComputedStyle), // old WebKit
  debugAlert: _debugAlert,
  hex:        _hex,
  mix:        _mix,
  toArray:    _toArray
};

// uuMeta.uid - get element unique id
_uid = function(elm) { // @param Node:
                       // @return String: "uuqid{n}", n from 1
  return elm[UNIQUEID] || (elm[UNIQUEID] = ++_win[UNIQUEID]);
};

// uuMeta.boot - catch DOMContentReady/window.onload event
_boot = function(callback,       // @param Function:
                 highPriority) { // @param Boolean(= false):
  _bootFire ? callback() // run now
            : _bootOrder[highPriority ? 0 : 1].push(callback); // stock
};

_event = {
  // uuMeta.event.bind
  bind: function(elm,       // @param Node:
                 eventName, // @param String:
                 callback,  // @param Function: callback
                 capture) { // @param Boolean(= false):
    _ie ? elm.attachEvent("on" + eventName, callback)
        : elm.addEventListener(eventName, callback, capture || false);
  },
  // uuMeta.event.unbind
  unbind: function(elm,       // @param Node:
                   eventName, // @param String:
                   callback,  // @param Function: callback
                   capture) { // @param Boolean(= false):
    _ie ? elm.detachEvent("on" + eventName, callback)
        : elm.removeEventListener(eventName, callback, capture || false);
  },
  // uuMeta.event.stop
  stop: function(evt) { // @param EventObject(= undefined):
    evt = evt || _win.event;
    _ie ? (evt.cancelBubble = true) : evt.stopPropagation();
    _ie ? (evt.returnValue = false) : evt.preventDefault();
  }
};

function bootFire(v) {
  if (!_bootFire++) {
    var step = "boot process";
    try {
      while ( (v = _bootOrder[0].shift()) ) { v(); } // high priority
      while ( (v = _bootOrder[1].shift()) ) { v(); } // low priority
      step = "window.boot";
      (typeof _win.boot === "function") && _win.boot(); // boot loader
    } catch(err) {
      _debugAlert && alert(step + " fail:" + err);
    }
  }
}

// --- initialize ---
// boot: windowReadyState and domReadyState
if (_ie) {
  _win.attachEvent("onload", bootFire);
  (function peek() {
    try {
      _doc.firstChild.doScroll("up"), bootFire();
    } catch(err) { setTimeout(peek, 16); }
  })();
} else { // WebKit, Firefox, Opera
  _win.addEventListener("load", bootFire, false);
  _doc.addEventListener("DOMContentLoaded", bootFire, false);
}

// prebuild element unique id ( node[UNIQUEID] )
_boot(function() {
  var node = _doc.getElementsByTagName("*"), v, i = 0, iz = node.length;

  for (; i < iz; ++i) {
    v = node[i];
    if (!_ie || v.nodeType === 1) {
      v[UNIQUEID] || (v[UNIQUEID] = ++_win[UNIQUEID]);
    }
  }
}, 1);

// init VML namespace
_ie && _boot(function() {
  var NS = 'urn:schemas-microsoft-com:', NSV = '#default#VML',
      ns = _doc.namespaces;

  if (!ns["v"]) {
    ns.add("v", NS + "vml", NSV);
    ns.add("o", NS + "office:office", NSV);
  }
  _doc.createStyleSheet().cssText =
    "canvas{display:inline-block;text-align:left;width:300px;height:150px}" +
    "v\:roundrect,v\:oval,v\:shape,v\:stroke,v\:fill,v\:textpath," +
    "v\:image,v\:line,v\:skew,v\:path,o\:opacity2" +
    "{behavior:url(" + NSV + ");display:inline-block}"; // inline-block [!]
});

// --- export ---
_win.uuMeta     = _meta;    // window.uuMeta
_win[UNIQUEID]  = 0;        // window.uuqid
_meta.uid       = _uid;     // window.uuMeta.uid
_meta.boot      = _boot;    // window.uuMeta.boot
_meta.event     = _event;   // window.uuMeta.event

})(); // uuMeta scope

